﻿using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Text;
using Medianamik.Core.Configuration;
using SWS = System.Web.Security;
using SWSR = System.Web.Security.Roles;
using System.Security.Principal;
using System.Web.Hosting;
using System.Web;
using System.Threading;
using Medianamik.Core.Interfaces;

namespace Medianamik.Core.Security
{
    static public class Roles
    {
        #region  Group Management

        static public bool IsUserInGroup(string username, string groupName)
        {
            return Provider.IsUserInGroup(username, groupName);
        }


        static public bool IsUserInGroup(string groupName)
        {
            return Provider.IsUserInGroup(GetCurrentUserName(), groupName);
        }

       

        static public string[] GetGroupsForUser(string username)
        {
            return Provider.GetGroupsForUser(username);
        }

        static public string[] GetGroupsForUser()
        {
            return Provider.GetGroupsForUser(GetCurrentUserName());
        }


        // group administration 
        // 

        static public string[] GetUsersInGroup(string groupName)
        {
            return Provider.GetUsersInGroup(groupName);
        }

        static public string[] GetGroupsInRole(string pRoleName)
        {
            return Provider.GetGroupsInRole(pRoleName);

        }
        


        static public void CreateGroup(string groupName, Guid parentGroupId)
        {
            Provider.CreateGroup(groupName, parentGroupId);
        }


        static public bool DeleteGroup(string groupName, bool throwOnPopulatedgroup)
        {
            return Provider.DeleteGroup(groupName, throwOnPopulatedgroup);
        }

        static public bool DeleteGroup(string groupName)
        {
            return Provider.DeleteGroup(groupName, true);
        }


        static public bool GroupExists(string groupName)
        {
            return Provider.GroupExists(groupName);
        }

        static public void AddRolesToGroup(string[] roleNames, string groupName)
        {
            Provider.AddRolesToGroups ( roleNames, new string[] { groupName });

        }

        static public void AddRoleToGroup(string roleName, string groupName)
        {
            Provider.AddRolesToGroups(new string[] {roleName}, new string[] { groupName });

        }

        static public void AddRoleToGroups(string roleName, string[] groupNames)
        {
            Provider.AddRolesToGroups(new string[] { roleName }, groupNames);

        }

        static public void AddUserToGroup(string username, string groupName)
        {
             Provider.AddUsersToGroups(new string[] { username }, new string[] { groupName });

        }


        static public void AddUserToGroups(string username, string[] groupNames)
        {
             Provider.AddUsersToGroups(new string[] { username },groupNames);

        }


        static public void AddUsersToGroup(string[] usernames, string groupName)
        {
            Provider.AddUsersToGroups( usernames , new string[] { groupName });

        }


        static public void AddUsersToGroups(string[] usernames, string[] groupNames)
        {
            Provider.AddUsersToGroups( usernames, groupNames );

        }

        static public void RemoveRolesFromGroup(string[] roleNames, string groupName)
        {
            Provider.RemoveRolesFromGroups(roleNames, new string[] { groupName });
        }
        static public void RemoveRoleFromGroups(string roleName, string[] groupNames)
        {
            Provider.RemoveRolesFromGroups(new string[] {roleName}, groupNames);
        }


        static public void RemoveUserFromGroup(string username, string groupName)
        {
            Provider.RemoveUsersFromGroups(new string[] {username}, new string[] {groupName });
        }


        static public void RemoveUserFromGroups(string username, string[] groupNames)
        {
            Provider.RemoveUsersFromGroups(new string[] { username }, groupNames );
        }


        static public void RemoveUsersFromGroup(string[] usernames, string groupName)
        {
            Provider.RemoveUsersFromGroups(usernames , new string[] { groupName });
        }

        static public void RemoveUsersFromGroups(string[] usernames, string[] groupNames)
        {
            Provider.RemoveUsersFromGroups(usernames, groupNames);
        }


        public static string[] GetAllGroups()
        {
            return Provider.GetAllGroups();
        }

        static public string[] FindUsersInGroup(string groupName, string usernameToMatch)
        {
            return Provider.FindUsersInGroup(groupName, usernameToMatch);
        }

        static public string[] GetRolesInGroup(string groupname)
        {
            return Provider.GetRolesInGroup(groupname);
        }

        #endregion

        public static int GetApprobationLevelForUser(Node node)
        {
            int grpIndex = 0;

            if (node == null || node.Approbation == null)
                return grpIndex;

            var grps = GetGroupsForUser();
            var grp = node.Approbation.GetGroups().Where(x => grps.Contains(x.Name)).LastOrDefault();

            if (grp != null)
            {
                grpIndex = node.Approbation.GetGroups().IndexOf(grp) + 1;
            }

            return grpIndex;
        }

        public static int GetApprobationLevelForUser(Guid nodeId)
        {
            int grpIndex = 0;

            var approbation = SecurityManager.GetNodeApprobationByNodeId(nodeId);

            if (approbation == null)
                return grpIndex;

            var grps = GetGroupsForUser();
            var grp = approbation.GetGroups().Where(x => grps.Contains(x.Name)).LastOrDefault();

            if (grp != null)
            {
                grpIndex = approbation.GetGroups().IndexOf(grp) + 1;
            }

            return grpIndex;
        }

        public static bool UserCanPublish(Node node)
        {
            bool canPublish = IsUserInRole("PublishContent") && node.IsVersioned;

            if(canPublish && SecurityManager.ApprobationEnabled && node.Approbation != null)
            {
                canPublish &= GetApprobationLevelForUser(node) == node.Approbation.Level || UserIsSA();
            }

            return canPublish;
        }

        public static bool UserCanApprove(Node node)
        {
            bool canApprove = node.IsVersioned && SecurityManager.ApprobationEnabled;

            if (canApprove)
            {
                canApprove &= node.Approbation != null && GetApprobationLevelForUser(node) < node.Approbation.Level;
            }

            return canApprove;
        }

        public static bool UserIsSA()
        {
            return IsUserInGroup(MedianamikGroups.LoweredSuperAdminGroupName);
        }

        #region Helper Methods

        private static string GetCurrentUserName()
        {
            IPrincipal user = GetCurrentUser();
            if (user == null || user.Identity == null)
                return String.Empty;
            else
                return user.Identity.Name;
        }

        private static IPrincipal GetCurrentUser()
        {
            if (HostingEnvironment.IsHosted)
            {
                HttpContext cur = HttpContext.Current;
                if (cur != null)
                    return cur.User;
            }
            return Thread.CurrentPrincipal;
        }

        #endregion

        #region System.Web.Security.Role implementation

        static public MedianamikRoleProvider Provider { get { return (MedianamikRoleProvider)SWSR.Provider; } }

        static public SWS.RoleProviderCollection Providers { get { return SWSR.Providers; } }

        static public string CookieName { get { return SWSR.CookieName; } }

        static public bool CacheRolesInCookie { get { return SWSR.CacheRolesInCookie; } }

        static public int CookieTimeout { get { return SWSR.CookieTimeout; } }

        static public string CookiePath { get { return SWSR.CookiePath; } }

        static public bool CookieRequireSSL { get { return SWSR.CookieRequireSSL; } }

        static public bool CookieSlidingExpiration { get { return SWSR.CookieSlidingExpiration; } }

        static public SWS.CookieProtection CookieProtectionValue { get { return SWSR.CookieProtectionValue; } }

        static public bool CreatePersistentCookie { get { return SWSR.CreatePersistentCookie; } }

        static public string Domain { get { return SWSR.Domain; } }

        static public int MaxCachedResults { get { return SWSR.MaxCachedResults; } }


        static public bool Enabled
        {
            get
            {
                return SWSR.Enabled;
            }
        }


        static public string ApplicationName
        {
            get { return SWSR.ApplicationName; }
            set { SWSR.ApplicationName = value; }
        }

        // authorization 

        static public bool IsUserInRole(string username, string roleName)
        {
            return SWSR.IsUserInRole(username, roleName);
        }


        static public bool IsUserInRole(string roleName)
        {
            return SWSR.IsUserInRole(roleName);
        }


        static public string[] GetRolesForUser(string username)
        {
            return SWSR.GetRolesForUser(username);
        }

        static public string[] GetRolesForUser()
        {
            return SWSR.GetRolesForUser();
        }


        // role administration 
        // 

        static public string[] GetUsersInRole(string roleName)
        {
            return SWSR.GetUsersInRole(roleName);
        }


        static public void CreateRole(string roleName)
        {
            SWSR.CreateRole(roleName);
        }


        static public bool DeleteRole(string roleName, bool throwOnPopulatedRole)
        {
            return SWSR.DeleteRole(roleName, throwOnPopulatedRole);
        }

        static public bool DeleteRole(string roleName)
        {
            return SWSR.DeleteRole(roleName);
        }


        static public bool RoleExists(string roleName)
        {
            return SWSR.RoleExists(roleName);
        }


        public static string[] GetAllRoles()
        {
            return SWSR.GetAllRoles();
        }


        public static void DeleteCookie()
        {
            SWSR.DeleteCookie();
        }

        static public string[] FindUsersInRole(string roleName, string usernameToMatch)
        {
            return SWSR.FindUsersInRole(roleName, usernameToMatch);
        }

        #endregion

        #region CRUD Operations on nodes

        public static bool UserHasRight(string username, Guid nodeId, SecurityLevels level)
        {
            var node = NodeManager.GetNode(nodeId);
            return UserHasRight(username, node, level);
        }

        public static bool UserHasRight(Guid nodeId, SecurityLevels level)
        {
            var node = NodeManager.GetNode(nodeId);
            return UserHasRight(node, level);
        }

        static public bool UserHasRight(string username, INode node, SecurityLevels level)
        {
            return Provider.UserHasRight(username, node , level);
        }
        static public bool UserHasRight<T>(T node, SecurityLevels level)
            where T:INode
        {
            return Provider.UserHasRight(GetCurrentUserName(), node , level);
        }
        static public bool UserHasRight(Node node, SecurityLevels level)
        {
            return Provider.UserHasRight(GetCurrentUserName(), node , level);
        }
        static public bool UserHasRight(string username, NodeType type, SecurityLevels level)
        {
            return Provider.UserHasRight(username, type, level);
        }
        static public bool UserHasRight(NodeType type, SecurityLevels level)
        {
            return Provider.UserHasRight(GetCurrentUserName(), type, level);
        }
 
        #endregion
    }
}
